﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using TireService.Data;
using System.Configuration;
using System.Collections;
using System.Web.Security;

namespace TireService.Web.Casehandling
{
    public partial class ServiceCarScheduleList : System.Web.UI.Page
    {

        #region Public Properties

        public int SelectedCarRowIndex
        {
            get
            {
                if (ViewState["_selectedcarrowindex"] != null)
                    return (int)ViewState["_selectedcarrowindex"];
                else
                    return -1;
            }
            set
            {
                ViewState["_selectedcarrowindex"] = value;
            }
        }

        public int SelectedPlannedCarRowIndex
        {
            get
            {
                if (ViewState["_selectedplannedcarrowindex"] != null)
                    return (int)ViewState["_selectedplannedcarrowindex"];
                else
                    return -1;
            }
            set
            {
                ViewState["_selectedplannedcarrowindex"] = value;
            }
        }

        /// <summary>
        /// PlannedCar - related to plan being edited
        /// </summary>
        public int PlannedServiceCarScheduleId
        {
            get
            {
                if (ViewState["_plannedservicecarscheduleid"] != null)
                    return (int)ViewState["_plannedservicecarscheduleid"];
                else
                    return 0;
            }
            set
            {
                ViewState["_plannedservicecarscheduleid"] = value;
            }
        }

        public int PlannedServiceCarId
        {
            get
            {
                if (ViewState["_plannedservicecarid"] != null)
                    return (int)ViewState["_plannedservicecarid"];
                else
                    return 0;
            }
            set
            {
                ViewState["_plannedservicecarid"] = value;
            }
        }

        public int PlannedEmployeeId
        {
            get
            {
                if (ViewState["_plannedemployeeid"] != null)
                    return (int)ViewState["_plannedemployeeid"];
                else
                    return 0;
            }
            set
            {
                ViewState["_plannedemployeeid"] = value;
            }
        }

        public DateTime PlannedScheduleDate
        {
            get
            {
                if (ViewState["_plannedscheduledate"] != null)
                    return (DateTime)ViewState["_plannedscheduledate"];
                else
                    return DateTime.MinValue;
            }
            set
            {
                ViewState["_plannedscheduledate"] = value;
            }
        }

        #endregion

        protected void Page_Init(object sender, EventArgs e)
        {
            // Register action button as full postback - otherwise it wount work because it is inside a update panel
            //ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
            //scriptManager.RegisterPostBackControl(this.btnRunAction.FindControl("btnRunAction"));
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            TireServiceDB db = new TireServiceDB();

            // Bind car data to gridview
            BindCustomerCarsNeedService(db);

            // Bind data to dropdown lists
            ddlEmployee.DataSource = db.GetEmployees(true);
            ddlEmployee.DataBind();

            ddlServiceCar.DataSource = db.GetServiceCars();
            ddlServiceCar.DataBind();

            if (Page.IsPostBack != true)
            {
                // Select first record i dropdownlists
                ddlEmployee.SelectedIndex = 0;
                ddlServiceCar.SelectedIndex = 0;
                calScheduleDate.SelectedDate = DateTime.Now;
            }

            // Bind ServiceCarSchedule gridview
            BindServiceCarScheduleDetail(db, Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(calScheduleDate.Value));

            //// Update hyperlinks to reports
            //UpdateReportLinks(Convert.ToInt32(ddlEmployee.Value), Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(calScheduleDate.Value));

            // Dispose connection to database
            db.Dispose();
        }

        #region Private Functions

        /// <summary>
        /// Function that bind customer cars that need service to gridview
        /// </summary>
        /// <param name="db">Connection to database</param>
        private void BindCustomerCarsNeedService(TireServiceDB db)
        {
            // Bind to gridview
            gvCarNeedService.DataSource = db.CustomerCarTireSetDistanceContainerViews.Where(p => p.CarStatusId == (int)Shared.CarStatus.NeedsTireChanged & p.ContainerCargoRoomId != null).OrderBy(p => p.Distance).ToList();
            gvCarNeedService.DataBind();

            gvCarNeedService.GroupBy(gvCarNeedService.Columns["ContainerNumber"]);
            gvCarNeedService.ExpandAll();
        }

        /// <summary>
        /// Function that bind already planned service schedules for a specific container to gridview
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="ContainerId">Id on container</param>
        private void BindPlannedServiceSchedule(TireServiceDB db, int ContainerId)
        {
            gvPlannedServiceSchedule.DataSource = db.ServiceCarScheduleDetailViews.Where(p => p.ContainerId == ContainerId & p.WorkCompleted == false).OrderBy(p => p.SequenceNumber).ToList();
            gvPlannedServiceSchedule.DataBind();

            gvPlannedServiceSchedule.GroupBy(gvPlannedServiceSchedule.Columns["ContainerNumber"]);
            gvPlannedServiceSchedule.GroupBy(gvPlannedServiceSchedule.Columns["ScheduleDate"]);
            gvPlannedServiceSchedule.ExpandAll();
        }

        /// <summary>
        /// Function that bind servicecarscheduledetails to gridview
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="ServiceCarId">Id on servicecar</param>
        /// <param name="ScheduleDate">Date for service</param>
        private void BindServiceCarScheduleDetail(TireServiceDB db, int ServiceCarId, DateTime ScheduleDate)
        {
            gvServiceCarScheduleDetail.DataSource = db.ServiceCarScheduleDetailViews.Where(p => p.ServiceCarId == ServiceCarId & p.ScheduleDate == ScheduleDate).OrderBy(p => p.SequenceNumber).ToList(); // db.GetServiceCarScheduleDetails(EmployeeId, ServiceCarId, ScheduleDate);
            gvServiceCarScheduleDetail.DataBind();
        }

        /// <summary>
        /// Function that bind cars that needs service and where tireset are located on a specific container
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="ContainerId">Id on container where tireset should be stored/located</param>
        private void BindNearestCarNeedService(TireServiceDB db, int ContainerId)
        {
            gvNearestCarNeedService.DataSource = db.CustomerCarTireSetDistanceContainerViews.Where(p => p.CarStatusId == (int)Shared.CarStatus.NeedsTireChanged & p.ContainerCargoRoomId != null & p.ContainerId == ContainerId).ToList();
            gvNearestCarNeedService.DataBind();
        }

        ///// <summary>
        ///// Function that updates report hyperlinks in UI based on selected values for employee, servicecar and scheduledate
        ///// </summary>
        ///// <param name="EmployeeId">Id on employee</param>
        ///// <param name="ServiceCarId">Id on servicecar</param>
        ///// <param name="ScheduleDate">Scheduledate</param>
        //private void UpdateReportLinks(int EmployeeId, int ServiceCarId, DateTime ScheduleDate)
        //{
        //    hlShowServiceCarSchedule.NavigateUrl = "~/Reports/View/ServiceCarScheduleReportView.aspx?EmployeeId=" + EmployeeId.ToString() + "&ServiceCarId=" + ServiceCarId.ToString() + "&ScheduleDate=" + ScheduleDate.ToShortDateString();
        //    //hlShowPackagingSchedule.NavigateUrl = 
        //}

        /// <summary>
        /// Function that adds new servicecarsheduledetail to existing servicecarschedule
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="MoveAfterSequenceNumber">True/false value indicating if the new detail record should be placed after the sequence number provided</param>
        /// <param name="SequenceNumber">Sequence number indicating where to put in the new detail record</param>
        /// <param name="ServiceCarScheduleId">Id on servicecarschedule to add the detail record to</param>
        /// <param name="SubscriptionId">Id on subscription</param>
        /// <param name="CarId">Id on car</param>
        /// <param name="TireSetId">Id on tireset to change to</param>
        /// <param name="Address">To address for the detail record</param>
        /// <param name="ZipCode">To zipccode for the detail record</param>
        /// <param name="City">To city for the detail record</param>
        /// <param name="CountryId">To country for the detail record</param>
        /// <param name="Longitude">To longitude for the detail record</param>
        /// <param name="Latitude">To latitude for the detail record</param>
        /// <returns>returns ServiceCarSchedule object</returns>
        private ServiceCarSchedule AddToServiceCarSchedule(TireServiceDB db, bool MoveAfterSequenceNumber, int SequenceNumber, int ServiceCarScheduleId, int SubscriptionId, int CarId, int TireSetId, string Address, string ZipCode, string City, int CountryId, string Longitude, string Latitude)
        {
            ServiceCarSchedule newschedule = db.GetServiceCarSchedule(ServiceCarScheduleId);

            if (newschedule == null)
            {
                throw new ArgumentException("Valgt plan for hjulskift kunne ikke findes.");
            }

            // Fetch all scheduledetails related to serviceschedule
            List<ServiceCarScheduleDetail> schedulelist = newschedule.ServiceCarScheduleDetails.OrderBy(p => p.SequenceNumber).ToList();

            // Create new scheduledetail
            ServiceCarScheduleDetail newscheduledetail = new ServiceCarScheduleDetail();

            // Check if sequence number is the last one in the schedulelist
            if (schedulelist.Count < SequenceNumber + Convert.ToInt32(MoveAfterSequenceNumber))
            {
                // Detail being created is the last one in the serviceschedule

                // Create new scheduledetail
                newscheduledetail = CreateServiceCarScheduleDetail(
                    db,
                    schedulelist.Last().ServiceCarId,
                    schedulelist.Last().ScheduleDate,
                    (SequenceNumber + Convert.ToInt32(MoveAfterSequenceNumber)),
                    SubscriptionId,
                    CarId,
                    TireSetId,
                    Address,
                    ZipCode,
                    City,
                    CountryId,
                    Longitude,
                    Latitude,
                    schedulelist.Last().ToAddress,
                    schedulelist.Last().ToZipCode,
                    schedulelist.Last().ToCity,
                    Convert.ToInt32(schedulelist.Last().ToCountryId),
                    schedulelist.Last().ToLongitude.ToString(),
                    schedulelist.Last().ToLatitude.ToString(),
                    newscheduledetail, 
                    (TimeSpan)schedulelist.Last().EndTime);
            }
            else
            {
                // Placeholder for calculating new endtime
                TimeSpan newendtime = new TimeSpan();

                foreach (ServiceCarScheduleDetail schedule in schedulelist)
                {
                    if (schedule.SequenceNumber >= SequenceNumber + Convert.ToInt32(MoveAfterSequenceNumber))
                    {
                        if (schedule.SequenceNumber == SequenceNumber + Convert.ToInt32(MoveAfterSequenceNumber))
                        {
                            // Create new scheduledetail
                            newscheduledetail = CreateServiceCarScheduleDetail(
                                db, 
                                schedule.ServiceCarId, 
                                schedule.ScheduleDate, 
                                (SequenceNumber + Convert.ToInt32(MoveAfterSequenceNumber)), 
                                SubscriptionId, 
                                CarId, 
                                TireSetId, 
                                Address, 
                                ZipCode, 
                                City, 
                                CountryId, 
                                Longitude, 
                                Latitude,
                                schedule.FromAddress, 
                                schedule.FromZipCode, 
                                schedule.FromCity, 
                                Convert.ToInt32(schedule.FromCountryId), 
                                schedule.FromLongitude.ToString(), 
                                schedule.FromLatitude.ToString(), 
                                newscheduledetail, 
                                (TimeSpan)schedule.StartTime);
                            
                            // Update "old" sequence
                            schedule.SequenceNumber = schedule.SequenceNumber + 1;
                            schedule.FromAddress = newscheduledetail.ToAddress;
                            schedule.FromZipCode = newscheduledetail.ToZipCode;
                            schedule.FromCity = newscheduledetail.ToCity;
                            schedule.FromCountryId = newscheduledetail.ToCountryId;
                            schedule.FromLongitude = newscheduledetail.ToLongitude;
                            schedule.FromLatitude = newscheduledetail.ToLatitude;

                            // Update drivingdistance and estimated driving time
                            UpdateServiceCarScheduleDetailDrivingValues(db, schedule);

                            // Calculate new suggested start and end time based on estimated drivingtime and worktime
                            UpdateServiceCarScheduleDetailStartEndTime(schedule, (TimeSpan)newscheduledetail.EndTime);
                            
                            // Update endtime placholder for new sequence numbers
                            newendtime = (TimeSpan)schedule.EndTime;
                        }
                        else
                        {
                            // Only update sequence number and start-/endtime
                            schedule.SequenceNumber = schedule.SequenceNumber + 1;

                            // Calculate new start-/end times
                            TimeSpan time = (TimeSpan)(schedule.EndTime - schedule.StartTime);
                            schedule.StartTime = newendtime;
                            schedule.EndTime = newendtime.Add(time);
                            newendtime = (TimeSpan)schedule.EndTime;
                        }
                    }
                }
            }

            db.AddServiceCarScheduleDetail(newscheduledetail);

            // Change status on car
            Car car = db.GetCar(Convert.ToInt32(newscheduledetail.CarId));

            if (car != null)
            {
                car.CarStatusId = (int)Shared.CarStatus.PlannedTireChange;
            }
            else
            {
                throw new ArgumentException("Fejl opstod - valgt bil og hjulsæt kunne ikke findes. Prøv igen eller kontakt IT administrator.");
            }

            return newschedule;
        }

        /// <summary>
        /// Function that creates a new servicecarschedule detail
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="ServiceCarId">Id on servicecar</param>
        /// <param name="ScheduleDate">Scheduledate</param>
        /// <param name="SequenceNumber">Sequence number for new detail record</param>
        /// <param name="SubscriptionId">Id on subscription</param>
        /// <param name="CarId">Id on car</param>
        /// <param name="TireSetId">Id on tireset to change to</param>
        /// <param name="ToAddress">To address for the detail record</param>
        /// <param name="ToZipCode">To zipccode for the detail record</param>
        /// <param name="ToCity">To city for the detail record</param>
        /// <param name="ToCountryId">To country for the detail record</param>
        /// <param name="ToLongitude">To longitude for the detail record</param>
        /// <param name="ToLatitude">To latitude for the detail record</param>
        /// <param name="FromAddress">From address for the detail record</param>
        /// <param name="FromZipCode">From zipcode for the detail record</param>
        /// <param name="FromCity">From city for the detail record</param>
        /// <param name="FromCountryId">From country for the detail record</param>
        /// <param name="FromLongitude">From longitude for the detail record</param>
        /// <param name="FromLatitude">From latitude for the detail record</param>
        /// <param name="newscheduledetail">Instantiated new detail record</param>
        /// <param name="StartTime">Startime for new detail record</param>
        /// <returns>returns created ServiceCarScheduleDetail object</returns>
        private ServiceCarScheduleDetail CreateServiceCarScheduleDetail(TireServiceDB db, int ServiceCarId, DateTime ScheduleDate, int SequenceNumber, int SubscriptionId, int CarId, int TireSetId, string ToAddress, string ToZipCode, string ToCity, int ToCountryId, string ToLongitude, string ToLatitude, string FromAddress, string FromZipCode, string FromCity, int FromCountryId, string FromLongitude, string FromLatitude, ServiceCarScheduleDetail newscheduledetail, TimeSpan StartTime)
        {
            newscheduledetail.ServiceCarId = ServiceCarId;
            newscheduledetail.ScheduleDate = ScheduleDate;
            newscheduledetail.SequenceNumber = SequenceNumber;
            newscheduledetail.CarId = CarId;
            newscheduledetail.FromTireSetId = db.GetCarTireSet(CarId, (int)Shared.TireSetStatus.MountedOnCar).TireSetId;
            newscheduledetail.ToTireSetId = Convert.ToInt32(TireSetId);

            newscheduledetail.FromAddress = FromAddress;
            newscheduledetail.FromZipCode = FromZipCode;
            newscheduledetail.FromCity = FromCity;
            newscheduledetail.FromCountryId = FromCountryId;
            newscheduledetail.FromLongitude = float.Parse(FromLongitude);
            newscheduledetail.FromLatitude = float.Parse(FromLatitude);

            newscheduledetail.ToAddress = ToAddress;
            newscheduledetail.ToZipCode = ToZipCode;
            newscheduledetail.ToCity = ToCity;
            newscheduledetail.ToCountryId = ToCountryId;
            newscheduledetail.ToLongitude = float.Parse(ToLongitude);
            newscheduledetail.ToLatitude = float.Parse(ToLatitude);

            UpdateServiceCarScheduleDetailDrivingValues(db, newscheduledetail);

            CreateServiceCarScheduleDetailTasklist(db, SubscriptionId, newscheduledetail);

            UpdateServiceCarScheduleDetailStartEndTime(newscheduledetail, StartTime);

            return newscheduledetail;
        }

        /// <summary>
        /// Function that updates drivingdistance and estimated driving time for a ServiceCarScheduleDetail
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="scheduledetail">ServiceCarScheduleDetail object to update</param>
        private static void UpdateServiceCarScheduleDetailDrivingValues(TireServiceDB db, ServiceCarScheduleDetail scheduledetail)
        {
            scheduledetail.DrivingDistance = Convert.ToDecimal(db.DistanceBetween((float)scheduledetail.FromLatitude, (float)scheduledetail.FromLongitude, (float)scheduledetail.ToLatitude, (float)scheduledetail.ToLongitude));
            if (scheduledetail.DrivingDistance <= 15)
            {
                scheduledetail.EstimatedDrivingTime = scheduledetail.DrivingDistance / 50;
            }
            if (scheduledetail.DrivingDistance > 15 & scheduledetail.DrivingDistance <= 50)
            {
                scheduledetail.EstimatedDrivingTime = scheduledetail.DrivingDistance / 70;
            }
            if (scheduledetail.DrivingDistance > 50)
            {
                scheduledetail.EstimatedDrivingTime = scheduledetail.DrivingDistance / 90;
            }
        }
        
        /// <summary>
        /// Function that updates start and endtime for a ServiceCarScheduleDetail
        /// </summary>
        /// <param name="scheduledetail">ServiceCarScheduleDetail object to update</param>
        /// <param name="StartTime">Starttime for ServiceCarScheduleDetail object</param>
        private static void UpdateServiceCarScheduleDetailStartEndTime(ServiceCarScheduleDetail scheduledetail, TimeSpan StartTime)
        {
            // Calculated suggested start and end time based on estimated drivingtime and worktime
            decimal totaltime = 0; // scheduledetail.ServiceCarScheduleTasklists.ToList().Sum(p => p.EstimatedTime) + scheduledetail.EstimatedDrivingTime;
            TimeSpan totalminutes = TimeSpan.FromMinutes(Convert.ToInt32(totaltime * 60));
            scheduledetail.StartTime = StartTime;
            scheduledetail.EndTime = scheduledetail.StartTime.Add(totalminutes);
        }

        /// <summary>
        /// Function that creates tasklist for schedule detail based on tasks included in subscription
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="SubscriptionId">Id on subscription</param>
        /// <param name="newscheduledetail">ServiceCarScheduleDetail object to create tasklist for</param>
        private static void CreateServiceCarScheduleDetailTasklist(TireServiceDB db, int SubscriptionId, ServiceCarScheduleDetail newscheduledetail)
        {
            // Fetch service tasks included in subscription
            List<SubscriptionServiceTasklistView> subscriptiontasklist = db.GetSubScriptionServiceTasklistView(SubscriptionId);

            //// Add ServiceCarScheduleTasklist for each included subscription service task
            //foreach (SubscriptionServiceTasklistView subscriptiontask in subscriptiontasklist)
            //{
            //    ServiceCarScheduleTasklist tasklist = new ServiceCarScheduleTasklist();

            //    newscheduledetail.ServiceCarScheduleTasklists.Add(tasklist);
            //    tasklist.ServiceTaskId = subscriptiontask.ServiceTaskId;
            //    tasklist.CoveredBySubscription = true;
            //    tasklist.ServiceTaskStatusId = (int)Shared.ServiceTaskStatus.Planned;
            //    tasklist.Price = 0;
            //    tasklist.EstimatedTime = subscriptiontask.EstimatedTime;

            //    db.AddServiceCarScheduleTasklist(tasklist);
            //}
        }

        /// <summary>
        /// Function that sends email to customer with planned service date, time and location and link for confirming or declining planned service
        /// </summary>
        /// <param name="CustomerEmail">Customer email that this email will be send to</param>
        /// <param name="CustomerName">Name on customer</param>
        /// <param name="TireSetType">Tiretype description (Winther/Summer)</param>
        /// <param name="ScheduleDate">Scheduledate for the service</param>
        /// <param name="TimeSpan">Timespan for the service</param>
        /// <param name="Address">Address for service</param>
        /// <param name="ZipCode">ZipCode for service</param>
        /// <param name="City">City for service</param>
        /// <param name="DetailGuid">Unik id for serviceschedule detail - used in email links</param>
        private void SendEmail(string CustomerEmail, string CustomerName, string TireSetType, string ScheduleDate, string TimeSpan, string Address, string ZipCode, string City, string DetailGuid, string CustomerId, string SubscriptionId, string CustomerSubscriptionId)
        {
            string Subject = "Booking af tid til hjulskift (Abonnement " + CustomerId + "-" + SubscriptionId + "-" + CustomerSubscriptionId + ")";
            string CustomerApprovalLink = ConfigurationManager.AppSettings["CustomerConfirmationURL"].ToString() + "?ApprovalId=" + DetailGuid;
            string CustomerDisapprovalLink = ConfigurationManager.AppSettings["CustomerConfirmationURL"].ToString() + "?ApprovalId=" + DetailGuid + "&Approve=false";
            bool test = Convert.ToBoolean(Convert.ToByte(ConfigurationManager.AppSettings["TestEnvironmentOn"]));
            Shared email = new Shared();

            Hashtable templateVars = new Hashtable();

            // Send email to customer
            templateVars.Add("CustomerName", CustomerName);
            templateVars.Add("TireSetType", TireSetType);
            templateVars.Add("ScheduleDate", ScheduleDate);
            templateVars.Add("TimeSpan", TimeSpan);
            templateVars.Add("Address", Address);
            templateVars.Add("ZipCode", ZipCode);
            templateVars.Add("City", City);
            templateVars.Add("CustomerApprovalLink", CustomerApprovalLink);
            templateVars.Add("CustomerDisapprovalLink", CustomerDisapprovalLink);
            Shared.Parser parser = new Shared.Parser(Server.MapPath("~/Reports/HtmlTemplates/CustomerEmail_ServiceSchedulePlan.htm"), templateVars);

            MembershipUser user = Membership.GetUser();

            email.SendEmail(CustomerEmail, ConfigurationManager.AppSettings["EmailAddress"].ToString(), parser.Parse(), Subject, true, test, user.Email, null, null);
        }

        /// <summary>
        /// Function that runs specific action
        /// </summary>
        /// <param name="Action">Id for action to run</param>
        protected void SubmitAction(int Action)
        {
            if (Action == 0)
            {
                throw new ArgumentException("Ingen handling valgt.");
            }
            if (Action == 1)
            {
                // Show serviceschedule

                // Client script for launching modal popup for editing scheduletime
                //ClientScript.RegisterStartupScript(this.GetType(), "keySchedule", "launchPlanningSheetWindow();", true);
                ScriptManager.RegisterStartupScript(this.btnRunAction.FindControl("btnRunAction"), this.GetType(), "keySchedule", "launchPlanningSheetWindow();", true);
            }
            if (Action == 2)
            {
                // Show packaging list
                
            }
            if (Action == 3)
            {
                // Send confirmation email to selected customer
                SendConfirmationEmailToSelected();
            }
            if (Action == 4)
            {
                // Send confirmation email to all
                SendConfirmationEmailToAll();

            }
            if (Action == 5)
            {
                // Set as customer confirmed
                CustomerConfirmed();
            }
            if (Action == 6)
            {
                // Remove customer confirmation
                CustomerDeclined();
            }
            if (Action == 7)
            {
                // Edit time

                TireServiceDB db = new TireServiceDB();

                // Fecth detail
                ServiceCarScheduleDetailView detail = db.ServiceCarScheduleDetailViews.SingleOrDefault(p => p.ServiceCarScheduleDetailId == Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ServiceCarScheduleDetailId")));

                hfServiceCarScheduleDetailId.Value = detail.ServiceCarScheduleDetailId.ToString();
                txtStartHour.Text = detail.StartTime.Hours.ToString();
                txtStartMinut.Text = detail.StartTime.Minutes.ToString();
                txtEndHour.Text = detail.EndTime.Hours.ToString();
                txtEndMinut.Text = detail.EndTime.Minutes.ToString();
                
                // Client script for launching modal popup for editing scheduletime
                ScriptManager.RegisterStartupScript(this.btnRunAction.FindControl("btnRunAction"), this.GetType(), "keyTime", "launchEditTimeScheduleModal();", true);
            }
            if (Action == 8)
            { 
                // Create/Edit note
                TireServiceDB db = new TireServiceDB();

                // Fecth detail
                ServiceCarScheduleDetailView detail = db.ServiceCarScheduleDetailViews.SingleOrDefault(p => p.ServiceCarScheduleDetailId == Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ServiceCarScheduleDetailId")));

                hfServiceCarScheduleDetailId.Value = detail.ServiceCarScheduleDetailId.ToString();
                txtNote.Text = detail.Note;

                // Client script for launching modal popup for editing note
                // ClientScript.RegisterStartupScript(this.GetType(), "keyNote", "launchEditNoteModal();", true);
                ScriptManager.RegisterStartupScript(this.btnRunAction.FindControl("btnRunAction"), this.GetType(), "keyNote", "launchEditNoteModal();", true);
            }

            if (Action == 9)
            { 
                // Show google map and streetview

                string longitude = gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ToLongitude").ToString().Replace(",", ".");
                string latitude = gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ToLatitude").ToString().Replace(",", ".");

                ScriptManager.RegisterStartupScript(this.btnRunAction.FindControl("btnRunAction"), this.GetType(), "keyNote", "initialize(" + latitude + ", " + longitude + ");", true);
            }

            if (Action == 10)
            {
                // Change to primary/secondary adress
                throw new ArgumentException("Ikke implementeret endnu.");
            }

            if (Action == 11)
            {
                // Change to custom adress
                throw new ArgumentException("Ikke implementeret endnu.");
            }

        }

        /// <summary>
        /// Function that sends confirmation email to selected customer
        /// </summary>
        private void SendConfirmationEmailToSelected()
        {
            // Instantiate database
            TireServiceDB db = new TireServiceDB();

            // Fecth detail
            ServiceCarScheduleDetailView detail = db.ServiceCarScheduleDetailViews.SingleOrDefault(p => p.ServiceCarScheduleDetailId == Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ServiceCarScheduleDetailId")));

            if (detail != null)
            {
                // Send email
                SendConfirmationEmail(db, detail);

                // commit changes to database
                db.SubmitChanges();

                lMessage.Text = "Email blev sendt afsted til kunde";
            }
            else
            {
                lMessage.Text = "Venligst vælg en planlagt udkørsel";
            }

            // Dispose database
            db.Dispose();
            
        }

        /// <summary>
        /// Function that sends confirmation emails to all customers in serviceschedule
        /// </summary>
        private void SendConfirmationEmailToAll()
        {
            // Instantiate database
            TireServiceDB db = new TireServiceDB();

            // Fetch serviceschedule details
            List<ServiceCarScheduleDetailView> scheduledetails = db.ServiceCarScheduleDetailViews.Where(p => p.ServiceCarId == Convert.ToInt32(ddlServiceCar.Value) & p.ScheduleDate == Convert.ToDateTime(calScheduleDate.Value)).ToList();

            foreach (ServiceCarScheduleDetailView scheduledetail in scheduledetails)
            {
                SendConfirmationEmail(db, scheduledetail);
            }

            // commit changes to database
            db.SubmitChanges();

            // Dispose database
            db.Dispose();

            lMessage.Text = "Email blev sendt afsted til kunder";
        }

        /// <summary>
        /// Function that confirms servicedetail for customer
        /// </summary>
        private void CustomerConfirmed()
        {
            if (this.SelectedPlannedCarRowIndex == -1)
            {
                throw new ArgumentException("Venligst vælg et hjulskift i planen som du ønsker at ændre til godkendt af kunden.");
            }

            // Instantiate database connection
            TireServiceDB db = new TireServiceDB();

            // Fecth detail to updateTime
            ServiceCarScheduleDetail detail = db.GetServiceCarScheduleDetail(Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ServiceCarScheduleDetailId")));

            // Update detail
            detail.CustomerConfirmed = true;

            // Commit changes to database
            db.SubmitChanges();

            // Bind ServiceCarSchedule gridview
            BindServiceCarScheduleDetail(db, Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(calScheduleDate.Value));

            // Set focused row again
            gvServiceCarScheduleDetail.FocusedRowIndex = this.SelectedPlannedCarRowIndex;

            // Dispose database connection
            db.Dispose();

            // Show message
            lMessage.Text = "Hjulskift blev angivet som godkendt af kunden.";
        }

        /// <summary>
        /// Function that declined servicedetail for customer
        /// </summary>
        private void CustomerDeclined()
        {
            if (this.SelectedPlannedCarRowIndex == -1)
            {
                throw new ArgumentException("Venligst vælg et hjulskift i planen som du ønsker at fjerne kundegodkendelse på.");
            }

            // Instantiate database connection
            TireServiceDB db = new TireServiceDB();

            // Fecth detail to updateTime
            ServiceCarScheduleDetail detail = db.GetServiceCarScheduleDetail(Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ServiceCarScheduleDetailId")));

            // Update detail
            detail.CustomerConfirmed = false;

            // Commit changes to database
            db.SubmitChanges();

            // Bind ServiceCarSchedule gridview
            BindServiceCarScheduleDetail(db, Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(calScheduleDate.Value));

            // Set focused row again
            gvServiceCarScheduleDetail.FocusedRowIndex = this.SelectedPlannedCarRowIndex;

            // Dispose database connection
            db.Dispose();

            // Show message
            lMessage.Text = "Hjulskift blev angivet som IKKE godkendt af kunden.";
        }

        /// <summary>
        /// Function that sends email to customer for a specific servicedetail
        /// </summary>
        /// <param name="db">Database connection</param>
        /// <param name="scheduledetail">Servicedetail</param>
        private void SendConfirmationEmail(TireServiceDB db, ServiceCarScheduleDetailView scheduledetail)
        {
            // Send email
            SendEmail(scheduledetail.Email, scheduledetail.Name, scheduledetail.TireTypeDescription, scheduledetail.ScheduleDate.ToShortDateString(), scheduledetail.StartTime.ToString() + "-" + scheduledetail.EndTime.ToString(), scheduledetail.ToAddress, scheduledetail.ToZipCode, scheduledetail.ToCity, scheduledetail.DetailGuid.ToString(), scheduledetail.CustomerId.ToString(), scheduledetail.SubscriptionId.ToString(), scheduledetail.CustomerSubscriptionId.ToString());

            // Update serviceschedule detail
            ServiceCarScheduleDetail updatescheduledetail = db.GetServiceCarScheduleDetail(scheduledetail.ServiceCarScheduleDetailId);
            updatescheduledetail.CustomerEmailSendCount = updatescheduledetail.CustomerEmailSendCount + 1;
        }

        

        #endregion

        #region Control Functions

        /// <summary>
        /// Calendar function that runs when day is being rendered. Change style based on planned serviceschedule
        /// </summary>
        protected void calScheduleDate_DayRender(object sender, DevExpress.Web.ASPxEditors.DayRenderEventArgs e)
        {
            try
            {
                TireServiceDB db = new TireServiceDB();

                // Check if schedule exists on this date (with selected employee and service car) if then highlight date
                if (db.ScheduleDateExists(Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(e.Day.DateTime)))
                {
                    e.Style.BackColor = System.Drawing.Color.Blue;
                }

                db.Dispose();
            }
            catch (Exception ex)
            {

            }
        }

        /// <summary>
        /// Dropdownlist function that runs when new employee is selected. Refresh serviceschedule gridview
        /// </summary>
        protected void ddlEmployee_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Check if ServiceCarSchedule gridview should be databound
            if (ddlServiceCar.Value != null & ddlEmployee.Value != null & calScheduleDate.Value != null)
            {
                TireServiceDB db = new TireServiceDB();

                BindServiceCarScheduleDetail(db, Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(calScheduleDate.Value));

                db.Dispose();
            }
        }

        /// <summary>
        /// Dropdownlist function that runs when new servicecar is selected. Refresh serviceschedule gridview
        /// </summary>
        protected void ddlServiceCar_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Check if ServiceCarSchedule gridview should be databound
            if (ddlServiceCar.Value != null & ddlEmployee.Value != null & calScheduleDate.Value != null)
            {
                TireServiceDB db = new TireServiceDB();

                BindServiceCarScheduleDetail(db, Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(calScheduleDate.Value));

                db.Dispose();
            }
        }

        /// <summary>
        /// Calendar function that runs when new date is selected. Refresh serviceschedule gridview
        /// </summary>
        protected void calScheduleDate_SelectionChanged(object sender, EventArgs e)
        {
            // Check if ServiceCarSchedule gridview should be databound
            if (ddlServiceCar.Value != null & ddlEmployee.Value != null & calScheduleDate.Value != null)
            {
                TireServiceDB db = new TireServiceDB();

                BindServiceCarScheduleDetail(db, Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(calScheduleDate.Value));

                db.Dispose();
            }
        }

        /// <summary>
        /// Button function that find nearest planned servicecarschedule and shows in dropdonwlist, calendar and gridview
        /// </summary>
        protected void lbtnFindNextServiceCarSchedule_Click(object sender, EventArgs e)
        {
            try
            {
                // Instantiate database connection
                TireServiceDB db = new TireServiceDB();

                List<ServiceCarSchedule> schedulelist = db.GetServiceCarSchedules(Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(calScheduleDate.Value));

                if (schedulelist.Count == 0)
                {
                    throw new ArgumentException("Der blev ikke fundet nogen planlagte hjulskift efter " + calScheduleDate.Value.ToString());
                }
                else
                {
                    ddlServiceCar.Value = schedulelist.First().ServiceCarId;
                    calScheduleDate.Value = schedulelist.First().ScheduleDate;

                    this.PlannedServiceCarId = schedulelist.First().ServiceCarId;
                    this.PlannedScheduleDate = schedulelist.First().ScheduleDate;
                    this.PlannedServiceCarScheduleId = schedulelist.First().ServiceCarScheduleId;

                    BindServiceCarScheduleDetail(db, this.PlannedServiceCarId, this.PlannedScheduleDate);

                    gvCarNeedService.FocusedRowIndex = -1;
                    gvNearestCarNeedService.Visible = false;
                    gvPlannedServiceSchedule.Visible = false;
                }


                // Dispose database connection
                db.Dispose();
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        /// <summary>
        /// Button function that send confirmation email to customer with planned service 
        /// </summary>
        protected void lbtnSendCustomerEmailConfirmation_Click(object sender, EventArgs e)
        {
            try
            {
                // Instantiate database
                TireServiceDB db = new TireServiceDB();

                // Fetch serviceschedule details
                List<ServiceCarScheduleDetailView> scheduledetails = db.ServiceCarScheduleDetailViews.Where(p => p.ServiceCarId == Convert.ToInt32(ddlServiceCar.Value) & p.ScheduleDate == Convert.ToDateTime(calScheduleDate.Value)).ToList();

                foreach (ServiceCarScheduleDetailView scheduledetail in scheduledetails)
                {
                    // Send email
                    SendEmail(scheduledetail.Email, scheduledetail.Name, scheduledetail.TireTypeDescription, scheduledetail.ScheduleDate.ToShortDateString(), scheduledetail.StartTime.ToString() + "-" + scheduledetail.EndTime.ToString(), scheduledetail.CustomerAddress, scheduledetail.CustomerZipCode, scheduledetail.CustomerCity, scheduledetail.DetailGuid.ToString(), scheduledetail.CustomerId.ToString(), scheduledetail.SubscriptionId.ToString(), scheduledetail.CustomerSubscriptionId.ToString());

                    // Update serviceschedule detail
                    ServiceCarScheduleDetail updatescheduledetail = db.GetServiceCarScheduleDetail(scheduledetail.ServiceCarScheduleDetailId);
                    updatescheduledetail.CustomerEmailSendCount = updatescheduledetail.CustomerEmailSendCount + 1;
                }

                // commit changes to database
                db.SubmitChanges();

                // Dispose database
                db.Dispose();

                lMessage.Text = "Email blev sendt afsted til kunder";
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        /// <summary>
        /// Button function that updates focused row in scheduledetaillist with customerconfirmation
        /// </summary>
        protected void lbtnCustomerConfirmed_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.SelectedPlannedCarRowIndex == -1)
                {
                    throw new ArgumentException("Venligst vælg et hjulskift i planen som du ønsker at ændre til godkendt af kunden.");
                }

                // Instantiate database connection
                TireServiceDB db = new TireServiceDB();

                // Fecth detail to updateTime
                ServiceCarScheduleDetail detail = db.GetServiceCarScheduleDetail(Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ServiceCarScheduleDetailId")));

                // Update detail
                detail.CustomerConfirmed = true;

                // Commit changes to database
                db.SubmitChanges();

                // Bind ServiceCarSchedule gridview
                BindServiceCarScheduleDetail(db, Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(calScheduleDate.Value));
                
                // Set focused row again
                gvServiceCarScheduleDetail.FocusedRowIndex = this.SelectedPlannedCarRowIndex;

                // Dispose database connection
                db.Dispose();

                // Show message
                lMessage.Text = "Hjulskift blev angivet som godkendt af kunden.";
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        /// <summary>
        /// Button function that updates focused row in scheduledetaillist and removes customerconfirmation
        /// </summary>
        protected void lbtnRemoveCustomerConfirmed_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.SelectedPlannedCarRowIndex == -1)
                {
                    throw new ArgumentException("Venligst vælg et hjulskift i planen som du ønsker at fjerne kundegodkendelse på.");
                }

                // Instantiate database connection
                TireServiceDB db = new TireServiceDB();

                // Fecth detail to updateTime
                ServiceCarScheduleDetail detail = db.GetServiceCarScheduleDetail(Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ServiceCarScheduleDetailId")));

                // Update detail
                detail.CustomerConfirmed = false;

                // Commit changes to database
                db.SubmitChanges();

                // Bind ServiceCarSchedule gridview
                BindServiceCarScheduleDetail(db, Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(calScheduleDate.Value));

                // Set focused row again
                gvServiceCarScheduleDetail.FocusedRowIndex = this.SelectedPlannedCarRowIndex;

                // Dispose database connection
                db.Dispose();

                // Show message
                lMessage.Text = "Hjulskift blev angivet som IKKE godkendt af kunden.";
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        /// <summary>
        /// Button function that runs selected action from dropdownlist
        /// </summary>
        protected void btnRunAction_Click(object sender, EventArgs e)
        {
            try
            {
                SubmitAction(Convert.ToInt32(ddlAction.SelectedItem.Value));
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        /// <summary>
        /// Button function that creates new servicecarschedule and schedule detail
        /// </summary>
        protected void btnCreateServiceCarSchedule_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.PlannedServiceCarScheduleId != 0)
                {
                    throw new ArgumentException("Der eksisterer allerede plan for servicebilen på denne dato.");
                }
                else
                {
                    if (this.SelectedCarRowIndex == -1)
                    {
                        throw new ArgumentException("Der skal vælges en bil som der skal skiftes hjul på.");
                    }
                    if (ddlEmployee.Value == null)
                    {
                        throw new ArgumentException("Medarbejder skal vælges.");
                    }
                    if (ddlServiceCar.Value == null)
                    {
                        throw new ArgumentException("Servicebil skal vælges.");
                    }
                    if (calScheduleDate.SelectedDate == null)
                    {
                        throw new ArgumentException("Dato skal vælges.");
                    }

                    // Initiate database connection
                    TireServiceDB db = new TireServiceDB();

                    // Create ServiceCarSchedule
                    ServiceCarSchedule schedule = new ServiceCarSchedule();

                    schedule.ServiceCarId = Convert.ToInt32(ddlServiceCar.SelectedItem.Value);
                    schedule.ScheduleDate = calScheduleDate.SelectedDate;

                    db.AddServiceCarSchedule(schedule);

                    // Add scheduledetail
                    ServiceCarScheduleDetail scheduledetail = new ServiceCarScheduleDetail();
                    scheduledetail.ServiceCarId = Convert.ToInt32(ddlServiceCar.SelectedItem.Value);
                    scheduledetail.ScheduleDate = calScheduleDate.SelectedDate;
                    scheduledetail.SequenceNumber = 1;
                    scheduledetail.CarId = Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "CarId"));
                    scheduledetail.FromTireSetId = db.GetCarTireSet(Convert.ToInt32(scheduledetail.CarId), (int)Shared.TireSetStatus.MountedOnCar).TireSetId;
                    scheduledetail.ToTireSetId = Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "TireSetId"));
                    scheduledetail.FromAddress = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "Address"));
                    scheduledetail.FromZipCode = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "ZipCode"));
                    scheduledetail.FromCity = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "City"));
                    scheduledetail.FromCountryId = Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "CountryId"));
                    scheduledetail.FromLongitude = float.Parse(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "Longitude").ToString());
                    scheduledetail.FromLatitude = float.Parse(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "Latitude").ToString());
                    if (cbUserCarSecondaryAddress.Checked)
                    {
                        if (Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "DistanceSecondary")) == 0 | Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "DistanceSecondary")) == null)
                        {
                            throw new ArgumentException("Der er ikke angivet en sekundær adresse for kunden - anvend istedet primær adressen.");
                        }
                        else
                        {
                            scheduledetail.ToAddress = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SecondaryAddress"));
                            scheduledetail.ToZipCode = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SecondaryZipCode"));
                            scheduledetail.ToCity = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SecondaryCity"));
                            scheduledetail.ToCountryId = Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "CustomerCountryId"));
                            scheduledetail.ToLongitude = float.Parse(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudeSecondary").ToString());
                            scheduledetail.ToLatitude = float.Parse(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudeSecondary").ToString());
                            scheduledetail.DrivingDistance = Convert.ToDecimal(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "DistanceSecondary"));
                        }
                    }
                    else
                    {
                        scheduledetail.ToAddress = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "PrimaryAddress"));
                        scheduledetail.ToZipCode = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "PrimaryZipCode"));
                        scheduledetail.ToCity = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "PrimaryCity"));
                        scheduledetail.ToCountryId = Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "CustomerCountryId"));
                        scheduledetail.ToLongitude = float.Parse(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudePrimary").ToString());
                        scheduledetail.ToLatitude = float.Parse(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudePrimary").ToString());
                        scheduledetail.DrivingDistance = Convert.ToDecimal(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "Distance"));
                    }
                    if (scheduledetail.DrivingDistance <= 15)
                    {
                        scheduledetail.EstimatedDrivingTime = scheduledetail.DrivingDistance / 50;
                    }
                    if (scheduledetail.DrivingDistance > 15 & scheduledetail.DrivingDistance <= 50)
                    {
                        scheduledetail.EstimatedDrivingTime = scheduledetail.DrivingDistance / 70;
                    }
                    if (scheduledetail.DrivingDistance > 50)
                    {
                        scheduledetail.EstimatedDrivingTime = scheduledetail.DrivingDistance / 90;
                    }
                    scheduledetail.WorkCompleted = false;
                    scheduledetail.CustomerEmailSendCount = 0;
                    scheduledetail.CustomerConfirmed = false;

                    db.AddServiceCarScheduleDetail(scheduledetail);

                    // Fetch service tasks included in subscription
                    List<SubscriptionServiceTasklistView> subscriptiontasklist = db.GetSubScriptionServiceTasklistView(Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SubscriptionId")));

                    //// Add ServiceCarScheduleTasklist for each included subscription service task
                    //foreach (SubscriptionServiceTasklistView subscriptiontask in subscriptiontasklist)
                    //{
                        //ServiceCarScheduleTasklist tasklist = new ServiceCarScheduleTasklist();

                        //scheduledetail.ServiceCarScheduleTasklists.Add(tasklist);
                        //tasklist.ServiceTaskId = subscriptiontask.ServiceTaskId;
                        //tasklist.CoveredBySubscription = true;
                        //tasklist.ServiceTaskStatusId = (int)Shared.ServiceTaskStatus.Planned;
                        //tasklist.Price = 0;
                        //tasklist.EstimatedTime = subscriptiontask.EstimatedTime;

                        //db.AddServiceCarScheduleTasklist(tasklist);
                    //}

                    // Calculated suggeted start and end time based on estimated drivingtime and worktime
                    decimal totaltime = 0;// scheduledetail.ServiceCarScheduleTasklists.ToList().Sum(p => p.EstimatedTime) + scheduledetail.EstimatedDrivingTime;
                    TimeSpan totalminutes = TimeSpan.FromMinutes(Convert.ToInt32(totaltime * 60));
                    scheduledetail.StartTime = TimeSpan.Parse("08:00:00"); // TODO: Create dynamic parameter for starting time in system
                    scheduledetail.EndTime = scheduledetail.StartTime.Add(totalminutes);

                    // Change status on car
                    Car car = db.GetCar(Convert.ToInt32(scheduledetail.CarId));

                    if (car != null)
                    {
                        car.CarStatusId = (int)Shared.CarStatus.PlannedTireChange;
                    }
                    else
                    {
                        throw new ArgumentException("Fejl opstod - valgt bil og hjulsæt kunne ikke findes. Prøv igen eller kontakt IT administrator.");
                    }

                    // Commit changes to database
                    db.SubmitChanges();

                    // Reset page properties
                    this.SelectedCarRowIndex = -1;

                    // Set new page properties
                    this.PlannedServiceCarScheduleId = schedule.ServiceCarScheduleId;
                    this.PlannedServiceCarId = schedule.ServiceCarId;
                    this.PlannedScheduleDate = schedule.ScheduleDate;

                    // Refresh gridview with cars that needs service 
                    BindCustomerCarsNeedService(db);

                    // Refresh servicecarschedule gridview
                    BindServiceCarScheduleDetail(db, schedule.ServiceCarId, schedule.ScheduleDate);

                    // Dispose database connection
                    db.Dispose();

                    // Update/reset message
                    lMessage.Text = "Plan oprettet og hjulskifte tilføjet";
                }
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        /// <summary>
        /// Button function that updates start/end time for servicescheduledetail
        /// </summary>
        protected void btnEditTimeSchedule_Click(object sender, EventArgs e)
        {
            try
            {
                if (hfServiceCarScheduleDetailId.Value != "")
                {
                    TireServiceDB db = new TireServiceDB();

                    // Fecth detail
                    ServiceCarScheduleDetail detail = db.GetServiceCarScheduleDetail(Convert.ToInt32(hfServiceCarScheduleDetailId.Value));

                    TimeSpan StartTime = new TimeSpan(Convert.ToInt32(txtStartHour.Text), Convert.ToInt32(txtStartMinut.Text), 0);
                    TimeSpan EndTime = new TimeSpan(Convert.ToInt32(txtEndHour.Text), Convert.ToInt32(txtEndMinut.Text), 0);

                    detail.StartTime = StartTime;
                    detail.EndTime = EndTime;

                    db.SubmitChanges();

                    // Refresh gridview
                    BindServiceCarScheduleDetail(db, detail.ServiceCarId, detail.ScheduleDate);

                    db.Dispose();
                }
                else
                {
                    throw new ArgumentException("Venligt vælg planlagt hjulskift at redigere start/slut tid på.");
                }
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        /// <summary>
        /// Button function that updates note for servicescheduledetail
        /// </summary>
        protected void btnEditNote_Click(object sender, EventArgs e)
        {
            try
            {
                if (hfServiceCarScheduleDetailId.Value != "")
                {
                    TireServiceDB db = new TireServiceDB();

                    // Fecth detail
                    ServiceCarScheduleDetail detail = db.GetServiceCarScheduleDetail(Convert.ToInt32(hfServiceCarScheduleDetailId.Value));

                    detail.Note = txtNote.Text;

                    db.SubmitChanges();

                    db.Dispose();
                }
                else
                {
                    throw new ArgumentException("Venligt vælg planlagt hjulskift at oprette/redigere note på.");
                }
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        #endregion

        #region GridView Functions

        /// <summary>
        /// Gridview function that change field data for unbound fields
        /// </summary>
        protected void gvCarNeedService_CustomUnboundColumnData(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewColumnDataEventArgs e)
        {
            //// Format UnBoundColumn CustomerSubscriptionDescription: Show subscription description
            //if (e.Column.FieldName == "CustomerSubscriptionDescription")
            //{
            //    // Get subscriptionid
            //    int subscriptionid = Convert.ToInt32(e.GetListSourceFieldValue("SubscriptionId"));

            //    TireServiceDB db = new TireServiceDB();

            //    // Change field value
            //    e.Value = db.GetSubscriptionDescription(subscriptionid);

            //    db.Dispose();
            //}

            //// Format UnBoundColumn BrandDescription: Show subscription description
            //if (e.Column.FieldName == "BrandDescription")
            //{
            //    // Get brandid
            //    int brandid = Convert.ToInt32(e.GetListSourceFieldValue("CarBrandId"));

            //    TireServiceDB db = new TireServiceDB();

            //    // Change field value
            //    e.Value = db.GetCarBrandDescription(brandid);

            //    db.Dispose();
            //}

            //// Format UnBoundColumn CarStatusDescription: Show car status
            //if (e.Column.FieldName == "CarStatusDescription")
            //{
            //    // Get carstatusid
            //    int carstatusid = Convert.ToInt32(e.GetListSourceFieldValue("CarStatusId"));

            //    TireServiceDB db = new TireServiceDB();

            //    // Change field value
            //    e.Value = db.GetCarStatusDescription(carstatusid);

            //    db.Dispose();
            //}
        }

        /// <summary>
        /// Gridview function that handles button clicks in gridview
        /// </summary>
        protected void gvCarNeedService_CustomButtonCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomButtonCallbackEventArgs e)
        {
            //if (e.ButtonID == "NearbyServiceSchedule")
            //{
            //    try
            //    {
            //        // Get ContainerId
            //        object cellContainerId = gvCarNeedService.GetRowValues(e.VisibleIndex, "ContainerId");

            //        TireServiceDB db = new TireServiceDB();

            //        // Show/Hide needed gridviews
            //        gvPlannedServiceSchedule.Visible = true;
            //        gvNearestCarNeedService.Visible = false;

            //        // Update gridview with planned services
            //        BindPlannedServiceSchedule(db, Convert.ToInt32(cellContainerId));

            //        // Dispose database connection
            //        db.Dispose();
            //    }
            //    catch (Exception ex)
            //    {
            //        if ((ex) is ArgumentException)
            //        {
            //            // User error - arguments not valid - show error message
            //            lMessage.Text = ((ArgumentException)ex).Message;
            //        }
            //        else
            //        {
            //            // System error - show general error message
            //            lMessage.Text = "Fejl opstod - venligst prøv igen";
            //        }
            //    }
            //    finally
            //    {
            //        // Update message panel
            //        upMessage.Update();
            //    }
            //}
        }

        /// <summary>
        /// Gridview function that runs when row has been selectedCarRowIndex
        /// </summary>
        protected void gvCarNeedService_FocusedRowChanged(object sender, EventArgs e)
        {
            if (Page.IsPostBack != false)
            {
                try
                {
                    // Set longitude/latitude for selected car
                    this.SelectedCarRowIndex = gvCarNeedService.FocusedRowIndex;

                    TireServiceDB db = new TireServiceDB();

                    // Show/Hide needed gridviews
                    gvPlannedServiceSchedule.Visible = true;
                    gvNearestCarNeedService.Visible = false;
                    this.SelectedPlannedCarRowIndex = -1;
                    gvServiceCarScheduleDetail.FocusedRowIndex = this.SelectedPlannedCarRowIndex;
                    

                    // Update gridview with planned services and show planned services for selected tireset container location
                    BindPlannedServiceSchedule(db, Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "ContainerId")));

                    // Dispose database connection
                    db.Dispose();
                }
                catch (Exception ex)
                {

                }
            }
        }

        /// <summary>
        /// Gridview function that handles button clicks in gridview
        /// </summary>
        protected void gvPlannedServiceSchedule_CustomButtonCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomButtonCallbackEventArgs e)
        {
            if (e.ButtonID == "InsertBefore")
            {
                try
                {
                    // Initiate database connection                        
                    TireServiceDB db = new TireServiceDB();

                    // Get sequence number
                    int SequenceNumber = Convert.ToInt32(gvPlannedServiceSchedule.GetRowValues(e.VisibleIndex, "SequenceNumber"));

                    // Define variable to be used for to address
                    string ToAddress; 
                    string ToZipCode;
                    string ToCity;
                    int ToCountryId;
                    string ToLongitude; 
                    string ToLatitude;

                    // Check if secondary address should be used
                    if (cbUserCarSecondaryAddress.Checked)
                    {
                        if (gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudeSecondary") == null | gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudeSecondary") == null)
                        {
                            throw new ArgumentException("Der er ikke angivet en sekundær adresse for kunden - anvend istedet primær adressen.");
                        }
                        else
                        {
                            ToAddress = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SecondaryAddress"));
                            ToZipCode = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SecondaryZipCode"));
                            ToCity = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SecondaryCity"));
                            ToCountryId = Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "CustomerCountryId"));
                            ToLongitude = gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudeSecondary").ToString();
                            ToLatitude = gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudeSecondary").ToString();
                        }
                    }
                    else
                    {
                        ToAddress = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "PrimaryAddress"));
                        ToZipCode = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "PrimaryZipCode"));
                        ToCity = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "PrimaryCity"));
                        ToCountryId = Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "CustomerCountryId"));
                        ToLongitude = gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudePrimary").ToString();
                        ToLatitude = gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudePrimary").ToString();
                    }

                    // Create new servicecarscheduledetail and add to existing serviceschedule
                    ServiceCarSchedule newschedule =
                        AddToServiceCarSchedule(db, 
                                                 false, 
                                                 SequenceNumber,
                                                 Convert.ToInt32(gvPlannedServiceSchedule.GetRowValues(e.VisibleIndex, "ServiceCarScheduleId")),
                                                 Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SubscriptionId")),
                                                 Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "CarId")),
                                                 Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "TireSetId")),
                                                 ToAddress,
                                                 ToZipCode,
                                                 ToCity,
                                                 ToCountryId,
                                                 ToLongitude,
                                                 ToLatitude);

                    // Commit changes to database
                    db.SubmitChanges();

                    // Reset page properties
                    this.SelectedCarRowIndex = -1;

                    // Set new page properties
                    this.PlannedServiceCarScheduleId = newschedule.ServiceCarScheduleId;
                    this.PlannedServiceCarId = newschedule.ServiceCarId;
                    this.PlannedScheduleDate = newschedule.ScheduleDate;

                    // Refresh gridview with cars that needs service 
                    BindCustomerCarsNeedService(db);

                    // Refresh or hide gridview with planned service again
                    if (gvCarNeedService.FocusedRowIndex > -1)
                    {
                        BindPlannedServiceSchedule(db, Convert.ToInt32(gvPlannedServiceSchedule.GetRowValues(e.VisibleIndex, "ContainerId")));
                    }
                    else
                    {
                        gvPlannedServiceSchedule.Visible = false;
                    }


                    // Refresh servicecarschedule gridview
                    BindServiceCarScheduleDetail(db, newschedule.ServiceCarId, newschedule.ScheduleDate);

                    // Select values in dropdownlists
                    ddlServiceCar.Value = newschedule.ServiceCarId;
                    calScheduleDate.Value = newschedule.ScheduleDate;

                    // Dispose database connection
                    db.Dispose();

                    // Update/reset message
                    lMessage.Text = "Plan justeret og hjulskifte tilføjet";
                }
                catch (Exception ex)
                {
                    if ((ex) is ArgumentException)
                    {
                        // User error - arguments not valid - show error message
                        lMessage.Text = ((ArgumentException)ex).Message;
                    }
                    else
                    {
                        // System error - show general error message
                        lMessage.Text = "Fejl opstod - venligst prøv igen";
                    }
                }
                finally
                {
                    // Update message panel
                    upMessage.Update();
                }
            }

            if (e.ButtonID == "InsertAfter")
            {
                try
                {
                    // Initiate database connection                        
                    TireServiceDB db = new TireServiceDB();

                    // Get sequence number
                    int SequenceNumber = Convert.ToInt32(gvPlannedServiceSchedule.GetRowValues(e.VisibleIndex, "SequenceNumber"));

                    // Define variable to be used for to address
                    string ToAddress;
                    string ToZipCode;
                    string ToCity;
                    int ToCountryId;
                    string ToLongitude;
                    string ToLatitude;

                    // Check if secondary address should be used
                    if (cbUserCarSecondaryAddress.Checked)
                    {
                        if (gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudeSecondary") == null | gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudeSecondary") == null)
                        {
                            throw new ArgumentException("Der er ikke angivet en sekundær adresse for kunden - anvend istedet primær adressen.");
                        }
                        else
                        {
                            ToAddress = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SecondaryAddress"));
                            ToZipCode = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SecondaryZipCode"));
                            ToCity = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SecondaryCity"));
                            ToCountryId = Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "CustomerCountryId"));
                            ToLongitude = gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudeSecondary").ToString();
                            ToLatitude = gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudeSecondary").ToString();
                        }
                    }
                    else
                    {
                        ToAddress = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "PrimaryAddress"));
                        ToZipCode = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "PrimaryZipCode"));
                        ToCity = Convert.ToString(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "PrimaryCity"));
                        ToCountryId = Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "CustomerCountryId"));
                        ToLongitude = gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudePrimary").ToString();
                        ToLatitude = gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudePrimary").ToString();
                    }

                    // Create new servicecarscheduledetail and add to existing serviceschedule
                    ServiceCarSchedule newschedule =
                        AddToServiceCarSchedule(db,
                                                 true,
                                                 SequenceNumber,
                                                 Convert.ToInt32(gvPlannedServiceSchedule.GetRowValues(e.VisibleIndex, "ServiceCarScheduleId")),
                                                 Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "SubscriptionId")),
                                                 Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "CarId")),
                                                 Convert.ToInt32(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "TireSetId")),
                                                 ToAddress,
                                                 ToZipCode,
                                                 ToCity,
                                                 ToCountryId,
                                                 ToLongitude,
                                                 ToLatitude);

                    // Commit changes to database
                    db.SubmitChanges();

                    // Reset page properties
                    this.SelectedCarRowIndex = -1;

                    // Set new page properties
                    this.PlannedServiceCarScheduleId = newschedule.ServiceCarScheduleId;
                    this.PlannedServiceCarId = newschedule.ServiceCarId;
                    this.PlannedScheduleDate = newschedule.ScheduleDate;

                    // Refresh gridview with cars that needs service 
                    BindCustomerCarsNeedService(db);

                    // Refresh or hide gridview with planned service again
                    if (gvCarNeedService.FocusedRowIndex > -1)
                    {
                        BindPlannedServiceSchedule(db, Convert.ToInt32(gvPlannedServiceSchedule.GetRowValues(e.VisibleIndex, "ContainerId")));
                    }
                    else
                    {
                        gvPlannedServiceSchedule.Visible = false;
                    }

                    // Refresh servicecarschedule gridview
                    BindServiceCarScheduleDetail(db, newschedule.ServiceCarId, newschedule.ScheduleDate);

                    // Select values in dropdownlists
                    ddlServiceCar.Value = newschedule.ServiceCarId;
                    calScheduleDate.Value = newschedule.ScheduleDate;

                    // Dispose database connection
                    db.Dispose();

                    // Update/reset message
                    lMessage.Text = "Plan justeret og hjulskifte tilføjet";
                }
                catch (Exception ex)
                {
                    if ((ex) is ArgumentException)
                    {
                        // User error - arguments not valid - show error message
                        lMessage.Text = ((ArgumentException)ex).Message;
                    }
                    else
                    {
                        // System error - show general error message
                        lMessage.Text = "Fejl opstod - venligst prøv igen";
                    }
                }
                finally
                {
                    // Update message panel
                    upMessage.Update();
                }
            }
        }

        /// <summary>
        /// Gridview function that change field data for unbound fields
        /// </summary>
        protected void gvPlannedServiceSchedule_CustomUnboundColumnData(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewColumnDataEventArgs e)
        {
            // Format UnBoundColumn DistancePrimary: Show distance from selected car's primary address to this car
            if (e.Column.FieldName == "DistancePrimary")
            {
                // 1. Fetch longitude/latitude from current car in planned serviceschedule gridview
                float carlongitude = float.Parse(e.GetListSourceFieldValue("ToLongitude").ToString());
                float carlatitude = float.Parse(e.GetListSourceFieldValue("ToLatitude").ToString());

                // Fetch longitude/latitude from selected car (primary) in need service gridview
                if (gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudePrimary") == null | gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudePrimary") == null)
                {
                    e.Value = "NA";
                }
                else
                {
                    // Calculate distance and show

                    // Initiate database connection
                    TireServiceDB db = new TireServiceDB();

                    e.Value = db.DistanceBetween(carlatitude, carlongitude, float.Parse(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudePrimary").ToString()), float.Parse(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudePrimary").ToString())).ToString();

                    // Dispose database connection
                    db.Dispose();
                }
            }

            // Format UnBoundColumn DistanceSecondary: Show distance from selected car secondary address to this car
            if (e.Column.FieldName == "DistanceSecondary")
            {
                // 1. Fetch longitude/latitude from current car in planned serviceschedule gridview
                float carlongitude = float.Parse(e.GetListSourceFieldValue("ToLongitude").ToString());
                float carlatitude = float.Parse(e.GetListSourceFieldValue("ToLatitude").ToString());

                // Fetch longitude/latitude from selected car (secondary) in need service gridview
                if (gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudeSecondary") == null | gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudeSecondary") == null)
                {
                    e.Value = "NA";
                }
                else
                {
                    // Calculate distance and show

                    // Initiate database connection
                    TireServiceDB db = new TireServiceDB();

                    e.Value = db.DistanceBetween(carlatitude, carlongitude, float.Parse(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LatitudeSecondary").ToString()), float.Parse(gvCarNeedService.GetRowValues(this.SelectedCarRowIndex, "LongitudeSecondary").ToString())).ToString();

                    // Dispose database connection
                    db.Dispose();
                }
            }

            if (e.Column.FieldName == "TotalTime")
            {
                decimal estimateddrivingtime = (decimal)e.GetListSourceFieldValue("EstimatedDrivingTime");
                decimal estimatedtime = (decimal)e.GetListSourceFieldValue("SumEstimatedTime");
                e.Value = estimateddrivingtime + estimatedtime;
            }
        }

        /// <summary>
        /// Gridview function that handles button clicks in gridview
        /// </summary>
        protected void gvNearestCarNeedService_CustomButtonCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomButtonCallbackEventArgs e)
        {
            if (e.ButtonID == "CarNeedServiceInsertBefore")
            {
                try
                {
                    // Initiate database connection                        
                    TireServiceDB db = new TireServiceDB();

                    // Get sequence number
                    int SequenceNumber = Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "SequenceNumber"));

                    // Store containerid
                    int ContainerId = Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "ContainerId"));

                    // Define variable to be used for to address
                    string ToAddress;
                    string ToZipCode;
                    string ToCity;
                    int ToCountryId;
                    string ToLongitude;
                    string ToLatitude;
                    bool MoveAfterSequenceNumber = false;

                    // Check if secondary address should be used
                    if (cbUserCarSecondaryAddress.Checked)
                    {
                        if (gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LongitudeSecondary") == null | gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LatitudeSecondary") == null)
                        {
                            throw new ArgumentException("Der er ikke angivet en sekundær adresse for kunden - anvend istedet primær adressen.");
                        }
                        else
                        {
                            ToAddress = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "SecondaryAddress"));
                            ToZipCode = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "SecondaryZipCode"));
                            ToCity = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "SecondaryCity"));
                            ToCountryId = Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "CustomerCountryId"));
                            ToLongitude = gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LongitudeSecondary").ToString();
                            ToLatitude = gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LatitudeSecondary").ToString();
                        }
                    }
                    else
                    {
                        ToAddress = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "PrimaryAddress"));
                        ToZipCode = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "PrimaryZipCode"));
                        ToCity = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "PrimaryCity"));
                        ToCountryId = Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "CustomerCountryId"));
                        ToLongitude = gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LongitudePrimary").ToString();
                        ToLatitude = gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LatitudePrimary").ToString();
                    }

                    // Create new servicecarscheduledetail and add to existing serviceschedule
                    ServiceCarSchedule newschedule =
                        AddToServiceCarSchedule(db,
                                                 MoveAfterSequenceNumber,
                                                 SequenceNumber,
                                                 Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ServiceCarScheduleId")),
                                                 Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "SubscriptionId")),
                                                 Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "CarId")),
                                                 Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "TireSetId")),
                                                 ToAddress,
                                                 ToZipCode,
                                                 ToCity,
                                                 ToCountryId,
                                                 ToLongitude,
                                                 ToLatitude);

                    // Commit changes to database
                    db.SubmitChanges();

                    // Refresh gridview with serviceschedule
                    BindServiceCarScheduleDetail(db, newschedule.ServiceCarId, newschedule.ScheduleDate);

                    // Reset selected car in customerneedservice
                    this.SelectedCarRowIndex = -1;

                    this.SelectedPlannedCarRowIndex = -1;
                    gvServiceCarScheduleDetail.FocusedRowIndex = this.SelectedPlannedCarRowIndex;

                    // TODO: Get below to work
                    //// Reset focused row and set focus to newly created car
                    //this.SelectedPlannedCarRowIndex = gvServiceCarScheduleDetail.FindVisibleIndexByKeyValue(newschedule.ServiceCarScheduleDetails.Single(p => p.SequenceNumber == (SequenceNumber + Convert.ToInt32(MoveAfterSequenceNumber))).ServiceCarScheduleDetailId);
                    //gvServiceCarScheduleDetail.FocusedRowIndex = this.SelectedPlannedCarRowIndex;

                    // Set new page properties
                    this.PlannedServiceCarScheduleId = newschedule.ServiceCarScheduleId;
                    this.PlannedServiceCarId = newschedule.ServiceCarId;
                    this.PlannedScheduleDate = newschedule.ScheduleDate;

                    // Refresh other gridviews based on newly selected planned car
                    BindCustomerCarsNeedService(db);
                    
                    gvNearestCarNeedService.Visible = false;
                    //BindNearestCarNeedService(db, ContainerId);
                    
                    // Dispose database connection
                    db.Dispose();

                    // Update/reset message
                    lMessage.Text = "Plan justeret og hjulskifte tilføjet";
                }
                catch (Exception ex)
                {
                    if ((ex) is ArgumentException)
                    {
                        // User error - arguments not valid - show error message
                        lMessage.Text = ((ArgumentException)ex).Message;
                    }
                    else
                    {
                        // System error - show general error message
                        lMessage.Text = "Fejl opstod - venligst prøv igen";
                    }
                }
                finally
                {
                    // Update message panel
                    upMessage.Update();
                }
            }

            if (e.ButtonID == "CarNeedServiceInsertAfter")
            {
                try
                {
                    // Initiate database connection                        
                    TireServiceDB db = new TireServiceDB();

                    // Get sequence number
                    int SequenceNumber = Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "SequenceNumber"));

                    // Store containerid
                    int ContainerId = Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "ContainerId"));

                    // Define variable to be used for to address
                    string ToAddress;
                    string ToZipCode;
                    string ToCity;
                    int ToCountryId;
                    string ToLongitude;
                    string ToLatitude;
                    bool MoveAfterSequenceNumber = true;

                    // Check if secondary address should be used
                    if (cbUserCarSecondaryAddress.Checked)
                    {
                        if (gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LongitudeSecondary") == null | gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LatitudeSecondary") == null)
                        {
                            throw new ArgumentException("Der er ikke angivet en sekundær adresse for kunden - anvend istedet primær adressen.");
                        }
                        else
                        {
                            ToAddress = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "SecondaryAddress"));
                            ToZipCode = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "SecondaryZipCode"));
                            ToCity = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "SecondaryCity"));
                            ToCountryId = Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "CustomerCountryId"));
                            ToLongitude = gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LongitudeSecondary").ToString();
                            ToLatitude = gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LatitudeSecondary").ToString();
                        }
                    }
                    else
                    {
                        ToAddress = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "PrimaryAddress"));
                        ToZipCode = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "PrimaryZipCode"));
                        ToCity = Convert.ToString(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "PrimaryCity"));
                        ToCountryId = Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "CustomerCountryId"));
                        ToLongitude = gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LongitudePrimary").ToString();
                        ToLatitude = gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "LatitudePrimary").ToString();
                    }

                    // Create new servicecarscheduledetail and add to existing serviceschedule
                    ServiceCarSchedule newschedule =
                        AddToServiceCarSchedule(db,
                                                 MoveAfterSequenceNumber,
                                                 SequenceNumber,
                                                 Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ServiceCarScheduleId")),
                                                 Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "SubscriptionId")),
                                                 Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "CarId")),
                                                 Convert.ToInt32(gvNearestCarNeedService.GetRowValues(e.VisibleIndex, "TireSetId")),
                                                 ToAddress,
                                                 ToZipCode,
                                                 ToCity,
                                                 ToCountryId,
                                                 ToLongitude,
                                                 ToLatitude);

                    // Commit changes to database
                    db.SubmitChanges();

                    // Refresh gridview with serviceschedule
                    BindServiceCarScheduleDetail(db, newschedule.ServiceCarId, newschedule.ScheduleDate);

                    // Reset selected car in customerneedservice
                    this.SelectedCarRowIndex = -1;

                    this.SelectedPlannedCarRowIndex = -1;
                    gvServiceCarScheduleDetail.FocusedRowIndex = this.SelectedPlannedCarRowIndex;

                    // TODO: Get below to work
                    //// Reset focused row and set focus to newly created car
                    //this.SelectedPlannedCarRowIndex = gvServiceCarScheduleDetail.FindVisibleIndexByKeyValue(newschedule.ServiceCarScheduleDetails.Single(p => p.SequenceNumber == (SequenceNumber + Convert.ToInt32(MoveAfterSequenceNumber))).ServiceCarScheduleDetailId);
                    //gvServiceCarScheduleDetail.FocusedRowIndex = this.SelectedPlannedCarRowIndex;

                    // Set new page properties
                    this.PlannedServiceCarScheduleId = newschedule.ServiceCarScheduleId;
                    this.PlannedServiceCarId = newschedule.ServiceCarId;
                    this.PlannedScheduleDate = newschedule.ScheduleDate;

                    // Refresh other gridviews based on newly selected planned car
                    BindCustomerCarsNeedService(db);
                    gvNearestCarNeedService.Visible = false;
                    //BindNearestCarNeedService(db, ContainerId);
                    
                    // Dispose database connection
                    db.Dispose();

                    // Update/reset message
                    lMessage.Text = "Plan justeret og hjulskifte tilføjet";
                }
                catch (Exception ex)
                {
                    if ((ex) is ArgumentException)
                    {
                        // User error - arguments not valid - show error message
                        lMessage.Text = ((ArgumentException)ex).Message;
                    }
                    else
                    {
                        // System error - show general error message
                        lMessage.Text = "Fejl opstod - venligst prøv igen";
                    }
                }
                finally
                {
                    // Update message panel
                    upMessage.Update();
                }
            }
        }

        /// <summary>
        /// Gridview function that change field data for unbound fields
        /// </summary>
        protected void gvNearestCarNeedService_CustomUnboundColumnData(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewColumnDataEventArgs e)
        {
            // Format UnBoundColumn DistancePrimary: Show distance from selected car's primary address to this car
            if (e.Column.FieldName == "DistanceToCarPrimary")
            {
                // Fetch longitude/latitude from selected car in needtirechange gridview
                float carlongitude = float.Parse(e.GetListSourceFieldValue("LongitudePrimary").ToString());
                float carlatitude = float.Parse(e.GetListSourceFieldValue("LatitudePrimary").ToString());

                // Fetch longitude/latitude from selected car in servicecarschedule gridview (primary) (The ToLongitude/ToLatitude)
                if (gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ToLongitude") == null | gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ToLatitude") == null)
                {
                    e.Value = "NA";
                }
                else
                {
                    // Calculate distance and show

                    // Initiate database connection
                    TireServiceDB db = new TireServiceDB();

                    if (this.SelectedPlannedCarRowIndex > -1)
                    {
                        e.Value = db.DistanceBetween(carlatitude, carlongitude, float.Parse(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ToLatitude").ToString()), float.Parse(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ToLongitude").ToString())).ToString();
                    }
                    else
                    {
                        e.Value = "";
                    }

                    // Dispose database connection
                    db.Dispose();
                }
            }

            // Format UnBoundColumn DistanceSecondary: Show distance from selected car secondary address to this car
            if (e.Column.FieldName == "DistanceToCarSecondary")
            {
                // Fetch longitude/latitude from current car (primary) (The ToLongitude/ToLatitude)
                if (e.GetListSourceFieldValue("LongitudeSecondary") == null | e.GetListSourceFieldValue("LatitudeSecondary") == null)
                {
                    e.Value = "NA";
                }
                else
                {
                    // Fetch longitude/latitude from selected car in needtirechange gridview
                    float carlongitude = float.Parse(e.GetListSourceFieldValue("LongitudeSecondary").ToString());
                    float carlatitude = float.Parse(e.GetListSourceFieldValue("LatitudeSecondary").ToString());
                    
                    // Calculate distance and show
                    
                    // Initiate database connection
                    TireServiceDB db = new TireServiceDB();

                    if (this.SelectedPlannedCarRowIndex > -1)
                    {
                        e.Value = db.DistanceBetween(carlatitude, carlongitude, float.Parse(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ToLatitude").ToString()), float.Parse(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ToLongitude").ToString())).ToString();
                    }
                    else
                    {
                        e.Value = "";
                    }

                    // Dispose database connection
                    db.Dispose();
                }
            }

            // Format UnBoundColumn SumEstimatedTime: Show sum of estimated servicetasks
            if (e.Column.FieldName == "SumEstimatedTime")
            {
                int detailid = Convert.ToInt32(e.GetListSourceFieldValue("ServiceCarScheduleDetailId"));

                TireServiceDB db = new TireServiceDB();

                decimal estimatedtime = 0; // db.GetServiceCarScheduleDetail(detailid).ServiceCarScheduleTasklists.Sum(p => p.EstimatedTime);

                e.Value = estimatedtime.ToString();

                db.Dispose();
            }

            // Format UnBoundColumn TotalTime: Show sum of driving time and estimated service task time
            if (e.Column.FieldName == "TotalTime")
            {
                decimal estimateddrivingtime = (decimal)e.GetListSourceFieldValue("EstimatedDrivingTime");
                decimal estimatedtime = (decimal)e.GetListSourceFieldValue("SumEstimatedTime");
                e.Value = estimateddrivingtime + estimatedtime;
            }
        }

        /// <summary>
        /// Gridview function that handles button clicks in gridview
        /// </summary>
        protected void gvServiceCarScheduleDetail_CustomButtonCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomButtonCallbackEventArgs e)
        {
            if (e.ButtonID == "MoveUp")
            {
                try
                {
                    // Initiate database connection                        
                    TireServiceDB db = new TireServiceDB();

                    int SequenceNumber = Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(e.VisibleIndex, "SequenceNumber")) - 1;
                    if (SequenceNumber == 0)
                    {
                        throw new ArgumentException("Planlagt hjulskift er først på planen og kan derfor ikke flyttes højere op.");
                    }    
                        
                    ServiceCarSchedule selectedschedule = db.GetServiceCarSchedule(Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(e.VisibleIndex, "ServiceCarScheduleId")));

                    if (selectedschedule == null)
                    {
                        throw new ArgumentException("Valgt plan for hjulskift kunne ikke findes.");
                    }

                    // Fetch schedule detail for update
                    ServiceCarScheduleDetail updateschedule = db.GetServiceCarScheduleDetail(Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(e.VisibleIndex, "ServiceCarScheduleDetailId")));

                    // Fetch all scheduledetails for serviceschedule
                    List<ServiceCarScheduleDetail> schedulelist = selectedschedule.ServiceCarScheduleDetails.OrderBy(p => p.SequenceNumber).ToList();

                    // Define placeholder propertie for endtime (whole plan needs to be updated with start/end time
                    TimeSpan newendtime = new TimeSpan();

                    foreach (ServiceCarScheduleDetail schedule in schedulelist)
                    {
                        if (schedule.SequenceNumber == SequenceNumber & schedule.ServiceCarScheduleDetailId != Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(e.VisibleIndex, "ServiceCarScheduleDetailId")))
                        {
                            // Update selected scheduledetail and move it backward
                            updateschedule.SequenceNumber = SequenceNumber;
                            updateschedule.FromAddress = schedule.FromAddress;
                            updateschedule.FromZipCode = schedule.FromZipCode;
                            updateschedule.FromCity = schedule.FromCity;
                            updateschedule.FromCountryId = schedule.FromCountryId;
                            updateschedule.FromLongitude = schedule.FromLongitude;
                            updateschedule.FromLatitude = schedule.FromLatitude;
                            UpdateServiceCarScheduleDetailDrivingValues(db, updateschedule);
                            
                            // Calculated suggested start and end time based on estimated drivingtime and worktime
                            UpdateServiceCarScheduleDetailStartEndTime(updateschedule, (TimeSpan)schedule.StartTime);
                            
                            // Update "old" sequence
                            schedule.SequenceNumber = schedule.SequenceNumber + 1;
                            schedule.FromAddress = updateschedule.ToAddress;
                            schedule.FromZipCode = updateschedule.ToZipCode;
                            schedule.FromCity = updateschedule.ToCity;
                            schedule.FromCountryId = updateschedule.ToCountryId;
                            schedule.FromLongitude = updateschedule.ToLongitude;
                            schedule.FromLatitude = updateschedule.ToLatitude;
                            UpdateServiceCarScheduleDetailDrivingValues(db, schedule);

                            // Calculate new suggested start and end time based on estimated drivingtime and worktime
                            UpdateServiceCarScheduleDetailStartEndTime(schedule, (TimeSpan)updateschedule.EndTime);

                            // Update placeholder for re-ordering of sequencenumber
                            newendtime = (TimeSpan)schedule.EndTime;
                        }
                        if (schedule.SequenceNumber > (SequenceNumber + 1))
                        {
                            // Calculate new start-/end times
                            TimeSpan time = (TimeSpan)(schedule.EndTime - schedule.StartTime);
                            schedule.StartTime = newendtime;
                            schedule.EndTime = newendtime.Add(time);

                            // Update placeholder for re-ordering of sequencenumber
                            newendtime = (TimeSpan)schedule.EndTime;
                        }
                    }

                    // Commit changes to database
                    db.SubmitChanges();

                    // Refresh gridview with serviceschedule
                    BindServiceCarScheduleDetail(db, selectedschedule.ServiceCarId, selectedschedule.ScheduleDate);

                    // Set new page properties
                    this.PlannedServiceCarScheduleId = selectedschedule.ServiceCarScheduleId;
                    this.PlannedServiceCarId = selectedschedule.ServiceCarId;
                    this.PlannedScheduleDate = selectedschedule.ScheduleDate;

                    // Hide nearest car need service gridview
                    gvNearestCarNeedService.Visible = false;

                    // Dispose database connection
                    db.Dispose();

                    // Update/reset message
                    lMessage.Text = "Hjulskift blev flyttet opad og plan blev justeret";
                }
                catch (Exception ex)
                {
                    if ((ex) is ArgumentException)
                    {
                        // User error - arguments not valid - show error message
                        lMessage.Text = ((ArgumentException)ex).Message;
                    }
                    else
                    {
                        // System error - show general error message
                        lMessage.Text = "Fejl opstod - venligst prøv igen";
                    }
                }
                finally
                {
                    // Update message panel
                    upMessage.Update();
                }
            }
            if (e.ButtonID == "MoveDown")
            {
                try
                {
                    // Initiate database connection                        
                    TireServiceDB db = new TireServiceDB();

                    int MoveSequence = 1;
                    int SequenceNumber = Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(e.VisibleIndex, "SequenceNumber")) + MoveSequence;
                    if (SequenceNumber == 0)
                    {
                        throw new ArgumentException("Planlagt hjulskift er først på planen og kan derfor ikke flyttes højere op.");
                    }    
                        
                    ServiceCarSchedule selectedschedule = db.GetServiceCarSchedule(Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(e.VisibleIndex, "ServiceCarScheduleId")));

                    if (selectedschedule == null)
                    {
                        throw new ArgumentException("Valgt plan for hjulskift kunne ikke findes.");
                    }

                    // Fetch schedule detail for update
                    ServiceCarScheduleDetail updateschedule = db.GetServiceCarScheduleDetail(Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(e.VisibleIndex, "ServiceCarScheduleDetailId")));

                    // Fetch all scheduledetails for serviceschedule
                    List<ServiceCarScheduleDetail> schedulelist = selectedschedule.ServiceCarScheduleDetails.OrderBy(p => p.SequenceNumber).ToList();

                    // Check if updateschedule is last in SequenceNumber
                    if (schedulelist.Last().SequenceNumber == updateschedule.SequenceNumber)
                    {
                        throw new ArgumentException("Planlagt hjulskift er sidst på planen og kan derfor ikke flyttes længere ned.");
                    }

                    // Define placeholder propertie for endtime (whole plan needs to be updated with start/end time)
                    TimeSpan newendtime = new TimeSpan();

                    foreach (ServiceCarScheduleDetail schedule in schedulelist)
                    {
                        if (schedule.SequenceNumber == SequenceNumber & schedule.ServiceCarScheduleDetailId != Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(e.VisibleIndex, "ServiceCarScheduleDetailId")))
                        {
                            // Update "old" sequence
                            schedule.SequenceNumber = schedule.SequenceNumber - MoveSequence;
                            schedule.FromAddress = updateschedule.FromAddress;
                            schedule.FromZipCode = updateschedule.FromZipCode;
                            schedule.FromCity = updateschedule.FromCity;
                            schedule.FromCountryId = updateschedule.FromCountryId;
                            schedule.FromLongitude = updateschedule.FromLongitude;
                            schedule.FromLatitude = updateschedule.FromLatitude;
                            UpdateServiceCarScheduleDetailDrivingValues(db, schedule);
                            
                            // Calculated suggested start and end time based on estimated drivingtime and worktime
                            UpdateServiceCarScheduleDetailStartEndTime(schedule, (TimeSpan)updateschedule.StartTime);
                            
                            // Update selected scheduledetail and move it backward
                            updateschedule.SequenceNumber = SequenceNumber;
                            updateschedule.FromAddress = schedule.ToAddress;
                            updateschedule.FromZipCode = schedule.ToZipCode;
                            updateschedule.FromCity = schedule.ToCity;
                            updateschedule.FromCountryId = schedule.ToCountryId;
                            updateschedule.FromLongitude = schedule.ToLongitude;
                            updateschedule.FromLatitude = schedule.ToLatitude;
                            UpdateServiceCarScheduleDetailDrivingValues(db, updateschedule);

                            // Calculate new suggested start and end time based on estimated drivingtime and worktime
                            UpdateServiceCarScheduleDetailStartEndTime(updateschedule, (TimeSpan)schedule.EndTime);

                            // Update placeholder for re-ordering of sequencenumber
                            newendtime = (TimeSpan)updateschedule.EndTime;
                        }
                        if (schedule.SequenceNumber > SequenceNumber)
                        {
                            // Calculate new start-/end times
                            TimeSpan time = (TimeSpan)(schedule.EndTime - schedule.StartTime);
                            schedule.StartTime = newendtime;
                            schedule.EndTime = newendtime.Add(time);

                            // Update placeholder for re-ordering of sequencenumber
                            newendtime = (TimeSpan)schedule.EndTime;
                        }
                    }

                    // Commit changes to database
                    db.SubmitChanges();

                    // Refresh gridview with serviceschedule
                    BindServiceCarScheduleDetail(db, selectedschedule.ServiceCarId, selectedschedule.ScheduleDate);

                    // Set new page properties
                    this.PlannedServiceCarScheduleId = selectedschedule.ServiceCarScheduleId;
                    this.PlannedServiceCarId = selectedschedule.ServiceCarId;
                    this.PlannedScheduleDate = selectedschedule.ScheduleDate;

                    // Hide nearest car need service gridview
                    gvNearestCarNeedService.Visible = false;

                    // Dispose database connection
                    db.Dispose();

                    // Update/reset message
                    lMessage.Text = "Hjulskift blev flyttet nedad og plan blev justeret";
                }
                catch (Exception ex)
                {
                    if ((ex) is ArgumentException)
                    {
                        // User error - arguments not valid - show error message
                        lMessage.Text = ((ArgumentException)ex).Message;
                    }
                    else
                    {
                        // System error - show general error message
                        lMessage.Text = "Fejl opstod - venligst prøv igen";
                    }
                }
                finally
                {
                    // Update message panel
                    upMessage.Update();
                }
            }
            //if (e.ButtonID == "UpdateTime")
            //{
            //    try
            //    {
            //        TireServiceDB db = new TireServiceDB();

            //        // Fecth detail
            //        ServiceCarScheduleDetailView detail = db.ServiceCarScheduleDetailViews.SingleOrDefault(p => p.ServiceCarScheduleDetailId == Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(e.VisibleIndex, "ServiceCarScheduleDetailId")));

            //        hfServiceCarScheduleDetailId.Value = detail.ServiceCarScheduleDetailId.ToString();
            //        txtStart.Value = detail.StartTime;
            //        txtEnd.Value = detail.EndTime;

            //        // Client script for launching modal popup for editing scheduletime
            //        ClientScript.RegisterStartupScript(this.GetType(), "key", "launchEditTimeScheduleModal();", true);
            //    }
            //    catch (Exception ex)
            //    {
            //        if ((ex) is ArgumentException)
            //        {
            //            // User error - arguments not valid - show error message
            //            lMessage.Text = ((ArgumentException)ex).Message;
            //        }
            //        else
            //        {
            //            // System error - show general error message
            //            lMessage.Text = "Fejl opstod - venligst prøv igen";
            //        }
            //    }
            //    finally
            //    {
            //        // Update message panel
            //        upMessage.Update();
            //    }
            //}
        }

        /// <summary>
        /// Gridview function that change field data for unbound fields
        /// </summary>
        protected void gvServiceCarScheduleDetail_CustomUnboundColumnData(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewColumnDataEventArgs e)
        {
            // Format UnBoundColumn EstimatedServiceTaskTime: Show sum of estimated servicetasks
            if (e.Column.FieldName == "EstimatedServiceTaskTime")
            {
                int detailid = Convert.ToInt32(e.GetListSourceFieldValue("ServiceCarScheduleDetailId"));

                TireServiceDB db = new TireServiceDB();

                decimal estimatedtime = 0; // db.GetServiceCarScheduleDetail(detailid).ServiceCarScheduleTasklists.Sum(p => p.EstimatedTime);

                e.Value = estimatedtime.ToString();

                db.Dispose();
            }
        }

        /// <summary>
        /// Gridview function that runs when user has confirmed to delete record
        /// </summary>
        protected void gvServiceCarScheduleDetail_RowDeleting(object sender, DevExpress.Web.Data.ASPxDataDeletingEventArgs e)
        {
            // Delete record
            try
            {
                e.Cancel = true;

                // Instantiate database connection
                TireServiceDB db = new TireServiceDB();

                int ServiceCarScheduleDetailId = Convert.ToInt32(e.Keys[0]);
                
                // Fetch scheduledetail
                ServiceCarScheduleDetail scheduledetail = db.GetServiceCarScheduleDetail(ServiceCarScheduleDetailId);

                if (scheduledetail.WorkCompleted)
                {
                    throw new ArgumentException("Hjulskift kan ikke slettes, da opgave er angivet som udført.");
                }

                // Fetch schedule 
                ServiceCarSchedule schedule = db.GetServiceCarSchedule(scheduledetail.ServiceCarId, scheduledetail.ScheduleDate);

                if (schedule == null)
                {
                    throw new ArgumentException("Valgt plan for hjulskift kunne ikke findes.");
                }

                // Fetch all scheduledetails for serviceschedule
                List<ServiceCarScheduleDetail> schedulelist = schedule.ServiceCarScheduleDetails.OrderBy(p => p.SequenceNumber).ToList();

                // Delete tasklist
                //db.ServiceCarScheduleTasklists.DeleteAllOnSubmit(scheduledetail.ServiceCarScheduleTasklists);

                // Delete scheduledetail
                db.ServiceCarScheduleDetails.DeleteOnSubmit(scheduledetail);

                // Reorder
                if (schedulelist.Count == 1)
                {
                    // Delete schedule
                    db.ServiceCarSchedules.DeleteOnSubmit(schedule);
                }
                else
                {
                    // Placeholder for new starttime
                    TimeSpan newstarttime = (TimeSpan)scheduledetail.StartTime;

                    foreach (ServiceCarScheduleDetail selectedscheduledetail in schedulelist)
                    {
                        if (selectedscheduledetail.SequenceNumber > scheduledetail.SequenceNumber)
                        {
                            // Update sequence number
                            selectedscheduledetail.SequenceNumber = selectedscheduledetail.SequenceNumber - 1;

                            // Calculate new start-/end times
                            TimeSpan time = (TimeSpan)(selectedscheduledetail.EndTime - selectedscheduledetail.StartTime);
                            selectedscheduledetail.StartTime = newstarttime;
                            selectedscheduledetail.EndTime = newstarttime.Add(time);

                            // Update placeholder for re-ordering of sequencenumber
                            newstarttime = (TimeSpan)selectedscheduledetail.EndTime;
                        }
                    }
                }

                // Change status on car
                Car car = db.GetCar(Convert.ToInt32(scheduledetail.CarId));

                if (car != null)
                {
                    car.CarStatusId = (int)Shared.CarStatus.NeedsTireChanged;
                }
                else
                {
                    throw new ArgumentException("Fejl opstod - valgt bil og hjulsæt kunne ikke findes. Prøv igen eller kontakt IT administrator.");
                }

                // Commit changes to database
                db.SubmitChanges();

                // Rebind gridviews
                BindCustomerCarsNeedService(db);
                BindServiceCarScheduleDetail(db, Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(calScheduleDate.Value));

                // Reset selected row and hide gridview with nearest car that need service
                if (this.SelectedPlannedCarRowIndex > -1)
                {
                    this.SelectedPlannedCarRowIndex = -1;
                    gvNearestCarNeedService.Visible = false;
                }

                // Dipose database connection
                db.Dispose();

                // Change message
                lMessage.Text = "Planlagt hjulskift blev slettet";
            }
            catch (Exception ex)
            {
                if ((ex) is ArgumentException)
                {
                    // User error - arguments not valid - show error message
                    lMessage.Text = ((ArgumentException)ex).Message;
                }
                else
                {
                    // System error - show general error message
                    lMessage.Text = "Fejl opstod - venligst prøv igen";
                }
            }
            finally
            {
                // Update message panel
                upMessage.Update();
            }
        }

        protected void gvServiceCarScheduleDetail_FocusedRowChanged(object sender, EventArgs e)
        {
            if (Page.IsPostBack != false)
            {
                try
                {
                    // Set selected rowindex propertie for car
                    this.SelectedPlannedCarRowIndex = gvServiceCarScheduleDetail.FocusedRowIndex;

                    TireServiceDB db = new TireServiceDB();

                    // Show/Hide needed gridviews
                    this.SelectedCarRowIndex = -1;
                    gvCarNeedService.FocusedRowIndex = this.SelectedCarRowIndex;
                    gvPlannedServiceSchedule.Visible = false;
                    gvNearestCarNeedService.Visible = true;

                    // Update gridview with cars that needs tireset changed that are close to this car
                    BindNearestCarNeedService(db, Convert.ToInt32(gvServiceCarScheduleDetail.GetRowValues(this.SelectedPlannedCarRowIndex, "ContainerId")));

                    // Dispose database connection
                    db.Dispose();
                }
                catch (Exception ex)
                {

                }
            }
        }

        /// <summary>
        /// Gridview function that runs when databinding - Changes colors based on customerconfirmed value
        /// </summary>
        protected void gvServiceCarScheduleDetail_HtmlRowPrepared(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewTableRowEventArgs e)
        {
            if (e.RowType != DevExpress.Web.ASPxGridView.GridViewRowType.Data) return;

            // Get customerconfirmed value - based on that rows will be formated
            bool CustomerConfirmed = Convert.ToBoolean(gvServiceCarScheduleDetail.GetRowValuesByKeyValue(e.KeyValue, "CustomerConfirmed"));

            if (CustomerConfirmed)
            {
                e.Row.BackColor = System.Drawing.Color.DarkGreen;
            }
            else
            {
                e.Row.BackColor = System.Drawing.Color.Orange;
            }
        }
        #endregion
    }
}